import java.net.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.Adler32;
import java.util.zip.Checksum;
import java.io.*;

public class ProjectManager
{

	private Server mainServer;
	private int port;
	private int bytesRead, fileSize, current;
	private boolean running;
	private long startOfProgram;
	private int download;
	private File cwd;
	public String testr = "A";

    public ConcurrentHashMap<Peer, Connection> activeConnections; // aka peers
    public ConcurrentHashMap<Peer, CopyOnWriteArraySet<FileDetails>> peerToFileMap;
    public ConcurrentHashMap<FileDetails, CopyOnWriteArraySet<Peer>> fileToPeerMap;
    public CopyOnWriteArraySet<FileDetails> localFileList;

	// public static ArrayList<Peer> peerList;
	// public static ArrayList<FileDetails> myFileList;

	public ProjectManager(int port)
	{
		running = true;
		activeConnections = new ConcurrentHashMap<Peer, Connection>();
		peerToFileMap = new ConcurrentHashMap<Peer, CopyOnWriteArraySet<FileDetails>>();
		fileToPeerMap = new ConcurrentHashMap<FileDetails, CopyOnWriteArraySet<Peer>>();
		localFileList = new CopyOnWriteArraySet<FileDetails>();
		this.port = port;
		startOfProgram = System.currentTimeMillis();
		cwd = new File("Files");
		if (cwd.isDirectory()) {
			System.out.println("this be a directory");
		}
		
		try
		{
			mainServer = new Server(port);
			mainServer.start();
		} catch (IOException e) {}
	}
	
	public File getCwd() {
		return cwd;
	}

	public void connectTo(Peer curPeer, int port)
	{
		Socket socket = null;
		try
		{
			socket = new Socket(curPeer.getIPAddr(), port);
		} catch (IOException e)
		{
		}
		Connection newConnection = new Connection(socket);
		activeConnections.putIfAbsent(curPeer, newConnection);
		newConnection.start();
		//download = newConnection.download();
		System.out.println("Connecting...");
		
		System.out.println("activeConnections: " + activeConnections.keySet());
	}

	public boolean isRunning()
	{
		return running;
	}

	public void shutdown()
	{
		running = false;
	}

	public InetAddress ipfilter(String ipString)
	{
		/*
		 * final String IPADDRESS_PATTERN =
		 * "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
		 * "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
		 * "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
		 * "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"; Pattern pattern =
		 * Pattern.compile(IPADDRESS_PATTERN); Matcher matcher =
		 * pattern.matcher(ipString); String groupStr =
		 * ""+matcher.group(1)+"."+matcher
		 * .group(2)+"."+matcher.group(3)+"."+matcher.group(4);
		 */
		try
		{
			return InetAddress.getByName(ipString);
		} catch (UnknownHostException e)
		{
			System.out.println("Address not valid, trying again...");
			e.printStackTrace();
		}
		final String IPADDRESS_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
		Pattern pattern = Pattern.compile(IPADDRESS_PATTERN);
		Matcher matcher = pattern.matcher(ipString);
		@SuppressWarnings("unused")
		String groupStr = "" + matcher.group(1) + "." + matcher.group(2) + "." + matcher.group(3) + "." + matcher.group(4);
		try
		{
			return InetAddress.getByName(ipString);
		} catch (UnknownHostException e)
		{
			System.out.println("Address still not valid. try again.");
			e.printStackTrace();
		}
		return null;
	}

	public long adlerHash(byte[] byt)
	{
		byte[] bytes = byt;
		System.out.println(bytes.length);
		// Compute Adler-32 checksum
		Checksum checksumEngine = new Adler32();
		checksumEngine.update(bytes, 0, bytes.length);
		long checksum = checksumEngine.getValue();
		System.out.println("checksum" + checksum);
		// The checksum engine can be reused again for a different byte array by
		// calling reset()
		checksumEngine.reset();
		return checksum;
	}

	public int getCurrentPort()
	{
		return port;
	}

	public void setPort(int prt)
	{
		port = prt;
	}

	public long getUptime()
	{
		return System.currentTimeMillis() - startOfProgram;
	}

	public void refresh()
	{
		if (localFileList == null) {
			System.out.println("i don't be lying fool");
		}
		FileNinja initNinja = new FileNinja(true);
		initNinja.start();
		System.out.println(localFileList);
		// refresh local files

		/*for (Peer key : activeConnections.keySet())
		{
			Connection curConnection = activeConnections.get(key);
			curConnection.setRefresh();
		}
		fileToPeerMap.clear();
		for (Peer key : peerToFileMap.keySet())
		{
			for (FileDetails value : peerToFileMap.get(key))
			{
				// fileToPeerMap.put(value, key);
			}
		}*/
	}// look into the directory..amnd check if every file has a details ..if not

	// then

	public void checkforDetails()
	{
		for (Peer peer : peerToFileMap.keySet())
		{
			for (FileDetails value : peerToFileMap.get(peer))
			{
				if (value.getName().equals(""))
				{

				}
			}
		}
	}
	
	public Server getMServ() {
		return mainServer;
	}

	// ConcurrentHashMap<Peer, Connection> activeConnections;
	// ConcurrentHashMap<Peer, Set<FileDetails>>
	// ConcurrentHashMap<FileDetails, Set<Peer>>

	public int getPerceDownload()
	{
		return download;
	}

	public void setBytesRead(int bytesRead) {
		this.bytesRead = bytesRead;
	}

	public int getBytesRead() {
		return bytesRead;
	}

	public void setFileSize(int fileSize) {
		this.fileSize = fileSize;
	}

	public int getFileSize() {
		return fileSize;
	}

	public void setCurrent(int current) {
		this.current = current;
	}

	public int getCurrent() {
		return current;
	}

	// need a way for to request files from other users and to see incoming
	// requests
	// no idea how to do that
	// have some sort of messaging system?
	// fire events?

}

/*
 * ------------------------- / Code Graveyard /* ------------------------- /
 * //ask for a specific file assuming the name of the file is known Scanner in =
 * new Scanner(System.in); PrintWriter writer = new
 * PrintWriter(socket.getOutputStream()); String nameOfFile = ""; while
 * (!nameOfFile.matches("n.*")) { StringBuilder msg = new StringBuilder();
 * System.out.println("Begin message; type ! by itself when done"); String line
 * = in.nextLine(); while (!line.equals("!")) { msg.append(line);
 * msg.append("\n"); line = in.nextLine(); }
 * 
 * writer.print(msg); writer.flush();
 * System.out.println("waiting for the requested file...");
 * 
 * // receive and read the file SUPPOSED TO BE IN A THREAD //byte [] mybytearray
 * = new byte [(int)file.length()];//not to use as we don't know the number of
 * byte [] bytesArray = new byte[fileSize]; InputStream is =
 * socket.getInputStream();
 * System.out.println("receiving the requested file..."); FileOutputStream fos =
 * new FileOutputStream("the new file"); BufferedOutputStream bos = new
 * BufferedOutputStream(fos); bytesRead =
 * is.read(bytesArray,0,bytesArray.length); current = bytesRead;
 * 
 * do { bytesRead = is.read(bytesArray, current, (bytesArray.length-current));
 * if(bytesRead >= 0) current += bytesRead; } while(bytesRead > -1);
 * 
 * bos.write(bytesArray, 0 , current); bos.flush(); long end =
 * System.currentTimeMillis(); //System.out.println(end-start); bos.close();
 * socket.close();
 */
